1 using System;
2 using
UnityEngine.Assertions;
3 using
Random = UnityEngine.Random;
4
5 namespace
ProceduralToolkit.Examples
6 {

7     ///
<summary>
8     ///
Generic cellular automaton for two-state rulesets
9     ///
</summary>
10     
public class CellularAutomaton
11     {
12         
[Serializable]
13         
public class Config
14         {
15             
public int width = 128;
16             
public int height = 128;
17             
public Ruleset ruleset = Ruleset.life;
18             
public float startNoise = 0.25f;
19             
public bool aliveBorders = false;
20         }
21
22         
public CellState[,] cells;
23
24         
private readonly Config config;
25         
private readonly Action<int, int> visitAliveBorders;
26         
private readonly Action<int, int> visitDeadBorders;
27         
private CellState[,] copy;
28         
private int aliveNeighbours;
29
30         
public CellularAutomaton(Config config)
31         {
32             Assert.IsTrue(config.width >
0);
33             Assert.IsTrue(config.height >
0);
34
35             
this.config = config;
36             cells =
new CellState[config.width, config.height];
37             copy =
new CellState[config.width, config.height];
38
39             visitAliveBorders = (
int neighbourX, int neighbourY) =>
40             {
41                 
if (copy.IsInBounds(neighbourX, neighbourY))
42                 {
43                     
if (copy[neighbourX, neighbourY] == CellState.Alive)
44                     {
45                         aliveNeighbours++;
46                     }
47                 }
48                 
else
49                 {
50                     aliveNeighbours++;
51                 }
52             };
53             visitDeadBorders = (
int neighbourX, int neighbourY) =>
54             {
55                 
if (copy[neighbourX, neighbourY] == CellState.Alive)
56                 {
57                     aliveNeighbours++;
58                 }
59             };
60
61             FillWithNoise(config.startNoise);
62         }
63
64         
public void Simulate(int generations)
65         {
66             
for (int i = 0; i < generations; i++)
67             {
68                 Simulate();
69             }
70         }
71
72         
public void Simulate()
73         {
74             PTUtils.Swap(
ref cells, ref copy);
75             
for (int x = 0; x < config.width; x++)
76             {
77                 
for (int y = 0; y < config.height; y++)
78                 {
79                     
int aliveCells = CountAliveNeighbourCells(x, y);
80
81                     
if (copy[x, y] == CellState.Dead)
82                     {
83                         
if (config.ruleset.CanSpawn(aliveCells))
84                         {
85                             cells[x, y] = CellState.Alive;
86                         }
87                         
else
88                         {
89                             cells[x, y] = CellState.Dead;
90                         }
91                     }
92                     
else
93                     {
94                         
if (!config.ruleset.CanSurvive(aliveCells))
95                         {
96                             cells[x, y] = CellState.Dead;
97                         }
98                         
else
99                         {
100                             cells[x, y] = CellState.Alive;
101                         }
102                     }
103                 }
104             }
105         }
106
107         
private void FillWithNoise(float noise)
108         {
109             
for (int x = 0; x < config.width; x++)
110             {
111                 
for (int y = 0; y < config.height; y++)
112                 {
113                     cells[x, y] = Random.
value < noise ? CellState.Alive : CellState.Dead;
114                 }
115             }
116         }
117
118         
private int CountAliveNeighbourCells(int x, int y)
119         {
120             aliveNeighbours =
0;
121             
if (config.aliveBorders)
122             {
123                 copy.VisitMooreNeighbours(x, y,
false, visitAliveBorders);
124             }
125             
else
126             {
127                 copy.VisitMooreNeighbours(x, y,
true, visitDeadBorders);
128             }
129             
return aliveNeighbours;
130         }
131     }
132 }


Gõ tìm kiếm nhanh...